Hoisting ⬆️

August 08, 2021

Small Example

console.log(x);
x = 5;
var x;
console.log(x);
Show output undefined
5

Compiled or interpreted?

This article isn’t about how JS engines work. To understand how hoisting works, let me tell you about the work of the JS engine in a simplified way. First, the code is compiled. The compiler finds and binds all declarations to the corresponding scopes. After that the code is executed

What changes after compilation?

The JS compiler creates variable declarations to the top of their scope for optimization. JS perceives var x = 5; as two commands. First - declare x, second - assign x the value 5. So, all variables are declared before any value is assigned to them. Let’s go back to the example. Try to rewrite the code from the example as it will look after compilation.

Show answer

var x;
console.log(x); // undefined
x = 5;
console.log(x); // 5

What about the functions?

Functions (function declaration) hoisting completely.

testWithDeclaration() // Hoisted

function testWithDeclaration() {
  console.log("Hoisted");
}
Show code after compilation

function testWithDeclaration() {
  console.log("Hoisted");
}

testWithDeclaration() // Hoisted


But

testWithExpression(); // TypeError

var testWithExpression = function() {
  console.log("Hoisted");
};
Show code after compilation

var testWithExpression; // undefined

testWithExpression(); // undefined() - TypeError

var testWithExpression = function() {
  console.log("Hoisted");
};


testWithArrowFunc(); // TypeError

var testWithArrowFunc = () => console.log("Hoisted");

Important

Hoisting is performed at the scope level. So variable declarations hoisting in their own scope and don’t hoisting in another one. Let’s look at an example.

test();

function test() {
  console.log(x);
  var x = 5;
}

Try to rewrite the code from the example as it will look after compilation.

Show answer

function test() {
  var x; // x hoisted in test function scope
  console.log(x); // undefined
  x = 5;
}

test();

let & const

JS also hoisting variables declared via let and const, but doesn’t initialize them with the undefined value, as it happens when using var

console.log(x); // ReferenceError: Cannot access 'x' before initialization

const x = 5;